
import os, sys, cv2, traceback
import numpy as np
parent_path = os.path.abspath(os.path.join(__file__, *(['..'] * 3)))
sys.path.insert(0, parent_path)

import time,threading, yaml
from core.task.task_pipeline import TaskPipeline
from core.utils.logger import logging

class ServerResponse():
    def __init__(self,
                 id,
                 code,
                 message = "",
                 data = {}
                 ) -> None:
        self.id = id
        self.code = code
        self.message:str = message
        self.data:dict = data
        self._data:dict = {
            "id": self.id,
            "code": self.code,
            "message":self.message,
            "data": self.data
        }
    def __getitem__(self, key):
        return self._data[key]
    
    def __setitem__(self, key, value):
        self._data[key] = value

class Server():
    """标准的服务器对象, 根据配置文件可以保存多个pipeline, 并且根据需求进行切换"""
    
    def __init__(self, server_cfg_path:str) -> None:
        self.project_rootdir = server_cfg_path[:server_cfg_path.find("/",server_cfg_path.find("projects")+9)]
        with open(server_cfg_path) as f:
            cfgs = yaml.safe_load(f)
            self._cfgs = cfgs
        self.task_pipelines = {}
        self.task_pipelines_cfgs = self._cfgs["TaskPipeline"]
        # init task pipeline
        for key, value in self.task_pipelines_cfgs.items():
            if value["enable"]:
                self.task_pipelines[key] = TaskPipeline(value["cfg"])
        
    
    def restart(self,):
        """根据项目根目录下的crontab_run.sh重启服务"""
        def _run():
            try:
                logging.info("|restart server...|")
                time.sleep(5)
                shell_file_path = self.project_rootdir + "/crontab_run.sh"
                os.popen("sh {}".format(shell_file_path))
            except Exception as e:
                logging.error(traceback.format_exc())
        try:
            logging.info("|/restart|")
            thread_1 = threading.Thread(target = _run)
            thread_1.start()
        except Exception as e:
            raise Exception(traceback.format_exc())
        
    def option(self, data):
        """ 服务配置项, 即针对服务本身的功能调用
        目包含 重启服务
        """
        id = data["id"]
        tag = data["tag"]
        if tag == "restart":
            self.restart()
        return data

    def task(self,data):
        """一级任务调用项
        TaskPipeline任务调用, 根据不同的Task, 进一步调用SubTask"""
        id = data["id"]
        tag = data["tag"]
        task_pipeline:TaskPipeline = self.task_pipelines[tag]
        sec_data = data["data"]
        sec_data["id"] = id
        data = self.sub_task(task_pipeline = task_pipeline, data = sec_data)
        return data
    
    def main_request(self,data):
        """
        请求入口, 建议所有的请求都从这里进入
        通过tag和data区分任务和系统设置
        """
        tag = data["tag"]
        id = data["id"]
        sec_data = data["data"]
        if isinstance(sec_data,dict):
            sec_data["id"] = id
        if tag == "task":
            data = self.task(sec_data)
        elif tag == "option":
            data = self.option(sec_data)
        return data
    # --- 二级任务配置
    def sub_task(self,task_pipeline:TaskPipeline, data):
        """
        二级任务调用项, 根据tag区分任务线下的子任务
        子任务包含 pop 作为固定tag, 其余tag根据配置文件确认
        """
        
        if data["tag"] == "pop":
            task_pipeline.task_pop(data)
        else:
            data = task_pipeline.task_add(data=data)
        return data

    def task_pop(self,task_tag, data):
        """
        关闭并弹出任务, 释放预测资源
        {
            tag: "task"
            data: {
                tag: pop
            }
        }
        """
        task_pipeline:TaskPipeline = self.task_pipelines[task_tag]
        task_pipeline.task_pop(data)
        return data

    def task_close(self,data):
        pass


if __name__ == "__main__":
    config_file_path = "projects/rooftop/configs/server_cfg.yml"
    server = Server(config_file_path)